package org.cqu_proj.demo.service;

import org.cqu_proj.demo.dao.UserFeaturesRepository;
import org.cqu_proj.demo.entity.User;
import org.cqu_proj.demo.entity.UserFeatures;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.*;

@Service
public class UserFeaturesService {
    // <editor-fold desc="用户特征的配置">
    private static final double DEFAULT_FEATURE_VALUE = 1.0;

    public final UserFeaturesRepository userFeatureRepository;

    // 通过构造函数注入依赖
    @Autowired
    public UserFeaturesService(UserFeaturesRepository userFeatureRepository) {
        this.userFeatureRepository = userFeatureRepository;
    }

    // </editor-fold>
    // <editor-fold desc="genres 与用户特征的映射关系">
    //
    private static final Map<String, Integer> userMap = new HashMap<>();
    static {
        userMap.put("Drama", 0);
        userMap.put("Comedy", 1);
        userMap.put("Action", 2);
        userMap.put("Thriller", 3);
        userMap.put("Adventure", 4);
        userMap.put("Romance", 5);
        userMap.put("Crime", 6);
        userMap.put("Sci-Fi", 7);
        userMap.put("Fantasy", 8);
        userMap.put("Children", 9);
        userMap.put("Mystery", 10);
        userMap.put("Animation", 11);
        userMap.put("Horror", 12);
        userMap.put("War", 13);
        userMap.put("IMAX", 14);
        userMap.put("Musical", 15);
        userMap.put("Western", 16);
        userMap.put("Documentary", 17);
        userMap.put("Film-Noir", 18);
        userMap.put("other", 19);
    }

    // </editor-fold>

    // <editor-fold desc="初始矩阵初始化">
    public List<Double> initUserFeature(int userId, double targetAvg) {
        // 固定均值
        double meanValue = targetAvg;
        // 设置波动范围 (标准差)
        double stdDev = 0.01; // 波动不太大，可以调整
        // 创建随机数生成器
        Random random = new Random();

        // 初始化特征矩阵
        List<Double> featureArray = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            // 生成符合正态分布的随机数
            double randomValue = meanValue + random.nextGaussian() * stdDev;
            featureArray.add(randomValue);
        }

        // 打印用户特征矩阵的值
        System.out.println("生成的用户特征矩阵：");
        for (int i = 0; i < featureArray.size(); i++) {
            System.out.println("索引 " + i + ": " + featureArray.get(i));
        }

        // 计算并打印实际均值
        double mean = featureArray.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        System.out.println("\n实际均值：" + mean);

        return featureArray;
    }
    public void saveUserFeatureToDatabase(int userId, List<Double> featureArray) {
        UserFeatures userFeature = new UserFeatures(userId, featureArray);
        userFeatureRepository.save(userFeature);
        System.out.println("用户特征已保存到数据库，用户ID: " + userId);
    }
    // </editor-fold>
    // <editor-fold desc="genres调整用户矩阵的工具方法">
        //获取userFeatures数据
    public List<Double> getUserFeaturesByUserId(int userId) {
        Optional<UserFeatures> userFeatureOptional = userFeatureRepository.findByUserId(userId);

        if (userFeatureOptional.isPresent()) {
            UserFeatures userFeature = userFeatureOptional.get();
            // 将 feature0 到 feature19 转换为 List<Double>
            List<Double> features = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                try {
                    String methodName = "getFeature" + i;
                    System.out.println("Trying to access method: " + methodName);
                    Method method = UserFeatures.class.getMethod(methodName);
                    features.add((Double) method.invoke(userFeature));
                } catch (NoSuchMethodException e) {
                    System.err.println("NoSuchMethodException: Method not found -> " + "getFeature" + i);
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return features;
        } else {
            // 用户特征不存在，返回空列表或处理异常
            return new ArrayList<>();
        }
    }
        //写回userFeatures数据
    public void updateUserFeatures(int userId, List<Double> newUserFeatures) {
            Optional<UserFeatures> userFeatureOptional = userFeatureRepository.findByUserId(userId);
            if (userFeatureOptional.isPresent()) {
                UserFeatures userFeature = userFeatureOptional.get();
                // 通过反射设置新的特征值
                for (int i = 0; i < 20; i++) {
                    try {
                        // 获取 setter 方法，并调用它设置值
                        Method method = UserFeatures.class.getMethod("setFeature" + i, double.class);
                        method.invoke(userFeature, newUserFeatures.get(i));
                    } catch (Exception e) {
                        // 处理异常，日志记录
                        e.printStackTrace();
                    }
                }
                userFeature.setSelectGenre(true);
                userFeatureRepository.save(userFeature); // 保存更新到数据库
            } else {
                  System.out.println("发生错误：在genres和用户矩阵更新时出现不存在的用户特征");
//                // 如果用户特征不存在，创建新的文档并保存
//                UserFeatures newUserFeature = new UserFeatures();
//                newUserFeature.setUserId(userId);
//                // 设置新特征
//                for (int i = 0; i < 20; i++) {
//                    try {
//                        // 获取 setter 方法，并调用它设置值
//                     = UserFeatures.class.getMethod("setFeature" + i, Double.class);
//                        method.invoke(newUserFeature, newUserFeatures.get(i));
//                    } catch (Exception e) {
//                        // 处理异常，日志记录
//                        e.printStackTrace();
//                    }
//                }
//                userFeatureRepository.save(newUserFeature); // 保存新文档到数据库
            }
        }
    // </editor-fold>
    // <editor-fold desc="根据genre更新矩阵方法">
    // Sigmoid函数计算
    public double sigmoid(double x, double k, double c) {
        return 1 / (1 + Math.exp(-k * (x - c)));
    }
    // 调整用户特征的方法
    public List<Double> adjustUserFeatures(List<Double> userFeatures, String genres, double targetAvg,
                                           double alpha, double sigmoidK, double minChange, double maxChange) {
        // 将genres字符串按逗号分割并去除空格
        String[] genreArray = genres.split(",");

        // 获取需要增加的索引集合
        Set<Integer> indicesToIncrease = new HashSet<>();
        for (String genre : genreArray) {
            if (userMap.containsKey(genre)) {
                indicesToIncrease.add(userMap.get(genre));  // 添加该类型的索引
            }
        }

        // 获取需要减少的索引集合
        Set<Integer> indicesToDecrease = new HashSet<>();
        for (int i = 0; i < userFeatures.size(); i++) {
            if (!indicesToIncrease.contains(i)) {
                indicesToDecrease.add(i);  // 需要减少的索引
            }
        }
        // 计算现有特征矩阵的均值
        double currentAvg = userFeatures.stream().mapToDouble(Double::doubleValue).average().orElse(0);

        // 计算需要增加或减少的总量
        double totalAdjustment = targetAvg - currentAvg;
        double adjustmentPerIndex = totalAdjustment / userFeatures.size();

        // 对所有特征进行调整

        // 对所有特征进行调整
        for (int i = 0; i < userFeatures.size(); i++) {
            double adjustmentFactor = sigmoid(userFeatures.get(i), sigmoidK, targetAvg); // 使用sigmoid控制增减幅度
            double change = alpha * adjustmentPerIndex * adjustmentFactor; // 计算增幅或减幅
            // 控制变化范围
            change = Math.max(minChange, Math.min(change, maxChange));

            if (indicesToIncrease.contains(i)) {
                // 对于需要增加的特征值，增加相应的值
                userFeatures.set(i, userFeatures.get(i) + change);
            } else if (indicesToDecrease.contains(i)) {
                // 对于需要减少的特征值，减少相应的值
                userFeatures.set(i, userFeatures.get(i) - change * 0.1); //减少的变化更小
            }
        }

        // 计算调整后的均值
        double adjustedAvg = userFeatures.stream().mapToDouble(Double::doubleValue).average().orElse(0);

        return userFeatures; // 返回调整后的特征矩阵
    }

    // </editor-fold>
    public void  updateUserMatrix(int userId,String genres){
       List<Double> featuresList= this.getUserFeaturesByUserId(userId);
       List<Double> featuresListNew=this.adjustUserFeatures(featuresList,genres,0.421,5,10,0.01,0.2);
       this.updateUserFeatures(userId,featuresListNew);
    }
    // 根据User对象处理相关逻辑
    public boolean handleUserFeatures(User user) {
        System.out.println("处理特征值");
        // 查找是否存在该用户的特征数据
        UserFeatures existingUserFeature ;
        Optional<UserFeatures> existingUserFeature1 = userFeatureRepository.findByUserId(user.getUserId());

        if (existingUserFeature1.isPresent()) {
            existingUserFeature = existingUserFeature1.get();
        }
        else  existingUserFeature=null;
        if (existingUserFeature == null) {
            // 如果没有找到用户数据，插入默认特征数据
            System.out.println("新用户的特征值-------------------不应该触发");
            System.out.println("处理特征值的userId:"+user.getUserId());
            userFeatureRepository.save(new UserFeatures(user.getUserId()));
            return true; // 返回true表示已新增
        } else {
            // 如果找到了用户数据，检查特征值是否一致
            System.out.println("用户的特征值检查是否选过偏好");
            return existingUserFeature.isSelectGenre();

            }
        }

    // 方便查看当前集合内容
    public void printUserFeatures() {
        List<UserFeatures> allUserFeatures = this.userFeatureRepository.findAll();
        allUserFeatures.forEach(uf -> System.out.println("UserId: " + uf.getUserId() + ", Features: " + uf));
    }
}
